#!BPY

""" Registration info for Blender menus:
Name: 'OpenGL (.cpp)...'
Blender: 243
Group: 'Export'
Tip: 'Exporte en instructions OpenGL (.cpp)'
"""

__author__ = "Matthieu Rejou, modifié par Olivier Buisard"
__url__ = ("blender", "", "http://conquest-legends.org",
	"")
__version__ = "1.0 2008-01-26"

__bpydoc__ = """\
Exporte en instructions OpenGL
"""

# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2008: Matthieu Rejou
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------

import Blender
from Blender import Object, Mesh, Material, Window, Image, Mathutils, Registry
from Blender import sys
import BPyMesh
import BPyObject
import BPySys
import BPyMessages
import string

##############################################
# C:\Windows\fichier => fichier
def split(path):
	idx = path.rfind('\\')
	if idx == -1:
		return path
	else:
		idx = idx + 1
		return path[idx:] 

#Fichier à écrire
class Fichier:	
	#Constructeur : ouvre le fichier et définit l'instance globale
	def __init__(self, filename):
		Fichier.instance = self
		self.nomBase = split(filename)
		self.nomFichier = filename + "GL.cpp"
	
	#Ouverture
	def ouvrir(self):
		""" ouvrir """
		print 'Ouverture du fichier ' + self.nomFichier
		self.fichier = open(self.nomFichier, 'wb')


	#Ecrit une chaîne de caractères
	def ecrire(self, chaine):
		self.fichier.write(chaine)


	#Ecrit une chaîne de caractères avec retour à la ligne
	def ecrireLn(self, chaine):
		self.fichier.write(chaine + '\n')


	#Ecrit un retour à la ligne
	def ln(self):
		self.fichier.write('\n')


	#Fermeture
	def fermer(self):
		print 'Fermeture du fichier'
		self.fichier.close()

#Convertis un flottant en chaîne de caractère en limitant la précision à 10^-6
def f_to_s(f):
	r = round(f,6)
	if r == int(r):
		return str(int(r))
	else:
		return str(r)

##############################################
#Classe descriptive d'un objet : groupe de vertexs + polygones
class Objet:
	def __init__(self, objetBlender):
		self.objetBlender = objetBlender
		self.nom = objetBlender.name
	
		#Mesh buffer
		mesh = Mesh.New('temp')
		mesh.getFromObject(objetBlender)
		matrice = objetBlender.getMatrix()

		#Récupération des vertexs
		self.verts = []
		for vert in mesh.verts:
			self.verts.append(Vertex(vert, matrice))

		#Récupération des polygones
		self.polys = []
		for face in mesh.faces:
			#Triangle
			if len(face.v) == 3:
				self.polys.append(Polygone(face.v, self.verts, face.no, matrice))
			
			#Quadrilatère
			elif len(face.v) == 4:
				vs = [face.v[0], face.v[1], face.v[2]]
				self.polys.append(Polygone(vs, self.verts, face.no, matrice))
				vs = [face.v[0], face.v[2], face.v[3]]
				self.polys.append(Polygone(vs, self.verts, face.no, matrice))

			#Ignoré
			else:
				print 'Un polygone à ' + str(len(face.v)) + ' sommets a été ignoré sur l\'objet ' + self.nom

##############################################
#Classe vertex
class Vertex:
	#Initialise le vertex
	def __init__(self, vert, matrice):
		self.index = vert.index
		#Coordonnées
		coords = self.getAbs(vert.co, matrice)
		self.x = coords[0]
		self.y = coords[1]
		self.z = coords[2]

	#Transforme un vecteur relatif en coordonnées absolues en fonction de la matrice de l'objet
	def getAbs(self, coords, matrice):
		vec = Mathutils.Vector([coords[0], coords[1], coords[2], 1])
		return vec * matrice

	#Retourne la ligne descriptive du matériau
	def toString(self):
		return '        glVertex3d(' + f_to_s(self.x) + ', ' + f_to_s(self.y) + ', ' + f_to_s(self.z) + ');\n'

##############################################
#Classe polygone
class Polygone:
	def __init__(self, vertsPoly, vertsObjet, normal, matrice):
		
		#Récupération des verticesface.v
		self.verts = []
		for vert in vertsPoly:
			self.verts.append(vertsObjet[vert.index])
		
		normal = self.getAbs(normal, matrice)
		self.nx = normal[0]
		self.ny = normal[1]
		self.nz = normal[2]
		
	#Transforme un vecteur relatif en coordonnées absolues en fonction de la matrice de l'objet
	def getAbs(self, coords, matrice):
		vec = Mathutils.Vector([coords[0], coords[1], coords[2], 1])
		return vec * matrice
		
	#Retourne la ligne descriptive du matériau
	def toString(self):
		return '        glNormal3d(' + f_to_s(self.nx) + ', ' + f_to_s(self.ny) + ', ' + f_to_s(self.nz) + ');\n' + \
			str(self.verts[0].toString()) + str(self.verts[1].toString()) + str(self.verts[2].toString())
		
##############################################
#Classe principale de l'exportation
class Export:
	def demarrer(self):
		print "Début de l'exportation"

		#Récupération des éléments
		print "Recuperation des objets"
		self.getObjets()

		#Ecriture du fichier
		print "Enregistrement des informations"
		Fichier.instance.ecrireLn('#include "' + Fichier.instance.nomBase + '.h"')
		Fichier.instance.ecrireLn("")
		nomClasse = Fichier.instance.nomBase
		Fichier.instance.ecrireLn("void " + string.capitalize(nomClasse) + "::creerListe() {")
		Fichier.instance.ecrireLn("    lid=glGenLists(1);")
		Fichier.instance.ecrireLn("    glNewList(lid, GL_COMPILE);")
		Fichier.instance.ecrireLn("    glBegin(GL_TRIANGLES);")
		self.ecrireObjets()
		Fichier.instance.ecrireLn("    glEnd();")
		Fichier.instance.ecrireLn("    glEndList();")
		Fichier.instance.ecrireLn("}")
		print "Fin de l'exportation"
	

	#Liste les objets
	def getObjets(self):
		#Liste globale d'objets
		self.objets = {}

		#Récupération des objets blender sélectionnés
		scene = Blender.Scene.GetCurrent()
		objets = list(scene.objects.context)
		objetsBlender = [o for o in objets if o.type == 'Mesh']

		#Mémorisation des objets
		for objet in objetsBlender:
			self.objets[objet.name] = Objet(objet)

	#Inscrit les objets dans le fichier
	def ecrireObjets(self):
		fichier = Fichier.instance
		for objet in self.objets.values():
			for poly in objet.polys:
				fichier.ecrireLn(poly.toString())
	

##############################################
#Lancement de l'import
def exporter(nomFichier):

	if not BPyMessages.Warning_SaveOver(nomFichier):
		return

	#Ouverture du fichier
	fichier = Fichier(nomFichier)
	fichier.ouvrir()

	#Export
	ex = Export()
	ex.demarrer()

	#Finalisation
	fichier.fermer()
	Blender.Draw.PupMenu('Exporte avec succes.')

if __name__ == '__main__':
	Window.FileSelector(exporter, 'Exporte GL instructions', sys.makename(ext=''))
